#ifndef __SORT_TYPE
#define __SORT_TYPE

#define DATATYPE_ABSTRACT		-1
#define DATATYPE_INTEGER		 0
#define DATATYPE_FLOAT			 1
#define DATATYPE_SYMBOL			 2
#define DATATYPE_FEATURETERM	 3
#define DATATYPE_SET			 4
#define DATATYPE_SPECIAL		 5

class Sort {
	friend class Ontology;
public:

	bool inSort(int i);
	bool inSort(float f);
	bool inSort(Symbol *s);
	bool inSort(class FeatureTerm *f);
	FeatureTerm *random(void);

	bool operator==(Sort &s);

	char *get(void);
	int get_data_type(void);
	Ontology *getOntology(void);

	bool hasFeature(Symbol *name);
	bool hasFeature(char *name);
	Sort *featureSort(Symbol *name);
	Sort *featureSort(char *name);
	FeatureTerm *featureDefaultValue(Symbol *name);
	FeatureTerm *featureDefaultValue(char *name);
	bool featureSingleton(Symbol *name);
	bool featureSingleton(char *name);

	~Sort();

	Sort *Antiunification(Sort *s);
	Sort *Unification(Sort *s);
	bool isSubsort(Sort *s);	/* checks whether 's' is a subsort of 'this' */ 
	bool is_a(Sort *s);			/* checks whether 'this' is a subsort of 's' */ 
	int refinementSteps(Sort *s);	// returns the distance in the sort hierarchy (only if this is a subsort of s)

	List<Sort> *getSubSorts(void);
	List<Symbol> *getFeatures(void);

	void addFeature(Symbol *name,Sort *sort,FeatureTerm *defaultvalue,bool singleton);
	void addFeature(char *name,char *sort,FeatureTerm *defaultvalue,Ontology *o,bool singleton);

	Sort *getSuper(void);

	void setSpecialSeed(class SpecialTerm *seed);
	class SpecialTerm *createSpecial(List<Symbol> *names,List<FeatureTerm> *arguments);	// uses m_seed to create a new SpecialTerm of the appropriate type

private:	
	Sort(); 
	Sort(Symbol *name,Sort *super,Ontology *o);
	Sort(char *name,char *super,Ontology *o);

	bool save(FILE *fp);

	Symbol *m_name;
	Sort *m_super;
	class Ontology *m_ontology;
	List<Sort> m_subsorts;

	bool m_defined;	/* when a sort has been used but not defined, this variable takes 'true' as value */ 

	int m_data_type;	

	List<Symbol> m_feature_names;
	List<Sort> m_feature_sorts;
	List<FeatureTerm> m_feature_default;
	List<bool> m_feature_singleton;		// Determines whether the feature can have a single value or if it can have many values

	class SpecialTerm *m_seed;	/* When a sort defines a SpecialTerm, this variable is used as the "seed",		*/ 
							/* it contains an empty SpecialTerm of the appropriate type, and to instantiate */ 
							/* a new SpecialTerm of this type, we only have to call the "newSpecialTerm"	*/ 
							/* virtual method of m_seed, that will call the apropriate constructor.			*/ 
}; /* Sort */ 

#endif

